--------------------------------------------------------------
-- 荣耀峡谷（龙族战场）
-- 因为活动以服为单位，建议合服时候直接清空活动数据
-- 休战->报名->匹配->侦查->战斗->休战
-- 规则说明 notice.xlsx-helpMisc-85

-- common db
-- db.state  					当前阶段
-- db.startTime 				阶段开始时间戳
-- db.endTime 					阶段结束时间戳
-- db.round						战斗阶段轮次
-- db.roundState				战斗阶段轮次状态
-- db.signList 					[本服]报名列表 [uuid]={roadIndex,zhandouli}
-- db.roadList 					[本服]各路入驻情况 [roadIndex]={[index]=uuid}
-- db.roadListSend 				[本服]同步列表
-- db.mainInfos 				[跨服]活动服基础信息
-- db.matchList 				[跨服]分组列表 [index]={svrIndex1, svrIndex2...}

--------------------------------------------------------------

local LuaMongo = _G.lua_mongo
local DB = require("common.DB")
local Config = require("Config")
local ValleyExcel = require("excel.valley")
local ValleyDefine = ValleyExcel.define[1]
local MailExcel = require("excel.mail")
local CommonDB = require("common.CommonDB")
local Util = require("common.Util")
local Lang = require("common.Lang")
local Msg = require("core.Msg")
local InnerMsg = require("core.InnerMsg")
local ObjHuman = require("core.ObjHuman")
local Broadcast = require("broadcast.Broadcast")
local Grid = require("bag.Grid")
local BagLogic = require("bag.BagLogic")
local CombatLogic = require("combat.CombatLogic")
local CombatDefine = require("combat.CombatDefine")
local CombatPosLogic = require("combat.CombatPosLogic")
local HeroGrid = require("hero.HeroGrid")
local JjcActLogic = require("jjc.JjcActLogic")
local MailManager = require("mail.MailManager")
local MiddleConnect = require("middle.MiddleConnect")
local RoleDBLogic = require("role.RoleDBLogic")
local RoleLogic = require("role.RoleLogic")
local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
local ValleyTask = require("valley.ValleyTask")
local ValleyMiddle = require("valley.ValleyMiddle")
local HeroLogic = require("hero.HeroLogic")

-- 活动状态
STATE_ACT_NO_OPEN = 0 	-- 未开放
STATE_ACT_READY = 1 	-- 休战
STATE_ACT_SIGN = 2 		-- 报名
STATE_ACT_MATCH = 3 	-- 匹配
STATE_ACT_EXPLORE = 4 	-- 侦查
STATE_ACT_FIGHT = 5 	-- 战斗(行军->准备->战斗)

-- 战斗阶段的状态
STATE_FIGHT_END = 0 	-- 结束
STATE_FIGHT_MOVE = 1 	-- 行军
STATE_FIGHT_READY = 2 	-- 准备/鼓舞
STATE_FIGHT_FIGHT = 3 	-- 战斗

ROAD_MAX_CNT = 3 		-- 一共有x路营地
ROAD_POINT_CNT = 3 		-- 每路有x个目标点
MAX_INSPIRE_CNT = 100 	-- 鼓舞进度条上限
TIMER_SEND_DATA = 3 	-- 每次发送x个玩家数据到跨服

local fakeHuman = {}

-- 获得活动最新状态 state, stateEndTime, stateStartTime
local function getNewState()
	local nowTime = os.time()
	local weekStartTime = Util.getWeekStartTime(nowTime)
	local scf = ValleyDefine.startTime
	local startTime = weekStartTime + (scf.week - 1) * 86400 + scf.hour * 3600 + scf.min * 60
	local ecf = ValleyDefine.endTime
	local endTime = weekStartTime + (ecf.week - 1) * 86400 + ecf.hour * 3600 + ecf.min * 60	
	if startTime <= nowTime and nowTime < endTime then
		local signEndTime = startTime + ValleyDefine.signTime
		if nowTime < signEndTime then
			return STATE_ACT_SIGN, signEndTime, startTime
		end
		local matchEndTime = signEndTime + ValleyDefine.matchTime
		if nowTime < matchEndTime then
			return STATE_ACT_MATCH, matchEndTime, signEndTime
		end
		local exploreEndTime = matchEndTime + ValleyDefine.exploreTime
		if nowTime < exploreEndTime then
			return STATE_ACT_EXPLORE, exploreEndTime, matchEndTime
		end
		return STATE_ACT_FIGHT, endTime, exploreEndTime
	end
	if nowTime < startTime then
		return STATE_ACT_READY, startTime, endTime - 7 * 86400
	end
	return STATE_ACT_READY, startTime + 7 * 86400, endTime
end

-- 获取活动当前状态(显示用)
function getState()
	if not _G.is_middle and MiddleConnect.IS_MIDDLE_CONNECT ~= true then
		return STATE_ACT_NO_OPEN, 0
	end	
	local commonDB = getCommonDB()
	if not commonDB.state then
		onTimer()
		commonDB = getCommonDB()
	end
	local leftTime = math.max(commonDB.endTime - os.time(), 0)
	return commonDB.state, leftTime, commonDB.startTime
end

-- 获取轮次信息 第x轮 阶段 
local function getNewRound(startTime)
	local time = math.max(os.time() - startTime, 1)
	local roundMaxTime = ValleyDefine.roundMoveTime + ValleyDefine.roundReadyTime + ValleyDefine.roundFightTime
	local round = math.ceil(time / roundMaxTime)
	local roundTime = time % roundMaxTime
	local roundStateEndTime = startTime + (round - 1) * roundMaxTime
	if roundTime < ValleyDefine.roundMoveTime then
		return round, STATE_FIGHT_MOVE, roundStateEndTime + ValleyDefine.roundMoveTime
	end
	if roundTime < ValleyDefine.roundMoveTime + ValleyDefine.roundReadyTime then
		return round, STATE_FIGHT_READY, roundStateEndTime + ValleyDefine.roundMoveTime + ValleyDefine.roundReadyTime
	end
	return round, STATE_FIGHT_FIGHT, roundStateEndTime + roundMaxTime
end

-- 获取活动当前轮次
function getRound()
	local commonDB = getCommonDB()
	if not commonDB.state then
		onTimer()
		commonDB = getCommonDB()
	end
	return commonDB.round, commonDB.roundState, commonDB.roundStateEndTime
end

-- 是否开放
function isOpen(human)
	local state, leftTime, startTime = getState()
	if state == STATE_ACT_NO_OPEN then -- 跨服未启动
		return Broadcast.sendErr(human, Lang.MIDDLE_SVR_ERR_CONNECT)
	end
	-- 判断开放等级+开服天数
--	if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_10013, true) then
--		return
--	end	
	return state, leftTime, startTime
end


----------------------------------------------- db --------------------------------------------------
-- 清空
function cleanDB()
	local commonDB = getCommonDB()
	commonDB.round = nil 
	commonDB.roundState = nil
	commonDB.signList = nil
	commonDB.roadList = nil
	commonDB.roadListSend = nil
	commonDB.mainInfos = nil
	commonDB.matchList = nil
	saveCommonDB(commonDB)
	LuaMongo.remove(DB.db_valley)
	LuaMongo.remove(DB.db_valley_record)
end

function saveCommonDB(data)
	data = data or {}
	CommonDB.updateValue(CommonDB.KEY_VALLEY, data)
end

local TEMP_COMMONDB = {}
function getCommonDB()
	return CommonDB.getValueByKey(CommonDB.KEY_VALLEY) or TEMP_COMMONDB
end

-- 是否报名 
function getSignData(uuid)
	local commonDB = getCommonDB()
	if not commonDB.signList then
		return
	end 
	return commonDB.signList[uuid]
end

-- 设置报名
function addSignData(human)
	local uuid = human.db._id
	local commonDB = getCommonDB()
	commonDB.signList = commonDB.signList or {}
	if commonDB.signList[uuid] then
		return
	end
	local signData = {}
	signData.roadIndex = 0 				-- 入驻x路
	signData.exploreCnt = 0 			-- 侦查次数 
	signData.exploreItems = nil 		-- 侦查未领取道具 [itemID] = itemCnt
	signData.exploreLogs = {} 			-- 侦查日志 [index] = id
	signData.zhandouli = human.db.zhandouli
	commonDB.signList[uuid] = signData
	saveCommonDB(commonDB)
	return signData
end

-- 获取入驻哪一路
function getRoadIndex(uuid)
	local signData = getSignData(uuid)
	if not signData then return end
	return signData.roadIndex
end

-- 获取某路的入驻列表
function getRoadUuids(roadIndex)
	local commonDB = getCommonDB()
	if not commonDB.roadList then
		return
	end 
	return commonDB.roadList[roadIndex]
end

-- 从某路移除
function delFromRoad(uuid, noSave)
	local signData = getSignData(uuid)
	if not signData or signData.roadIndex < 1 then
		return
	end
	local roadIndex = signData.roadIndex
	local uuids = getRoadUuids(roadIndex)
	local uuidsLen = uuids and #uuids or 0
	local cnt = 0
	for i = 1, uuidsLen do
		local tuuid = uuids[i]
		uuids[i] = nil
		if tuuid ~= uuid then
			cnt = cnt + 1
			uuids[cnt] = tuuid
		end
	end
	signData.roadIndex = 0
	if not noSave then
		saveCommonDB(commonDB)
	end
	return roadIndex
end

-- 入驻某路
function addToRoad(uuid, roadIndex, noSave)
	delFromRoad(uuid, true)
	local signData = getSignData(uuid)
	if not signData then return end
	if signData.roadIndex > 0 then
		return
	end
	if roadIndex < 1 then return end
	signData.roadIndex = roadIndex
	local commonDB = getCommonDB()
	commonDB.roadList = commonDB.roadList or {}
	if not commonDB.roadList[roadIndex] then
		commonDB.roadList[roadIndex] = {}
	end
	local cnt = #commonDB.roadList[roadIndex]
	commonDB.roadList[roadIndex][cnt + 1] = uuid
	if not noSave then
		saveCommonDB(commonDB)
	end
	return roadIndex
end

-- 生成侦查道具
function randomExploreID()
	local weight = 0
	for _, config in pairs(ValleyExcel.explore) do
		weight = weight + config.weight
	end
	if weight < 1 then return end
	local r = math.random(1, weight)
	for id, config in pairs(ValleyExcel.explore) do
		if r <= config.weight then
			return id, config
		end
		r = r - config.weight
	end
end

-- 平均战力
local function getMainInfoZDL()
	local commonDB = getCommonDB()
	if not commonDB.signList then
		return 0
	end
	local cnt = 0
	local sum = 0
	for _, signData in pairs(commonDB.signList) do
		cnt = cnt + 1
		sum = sum + signData.zhandouli
	end
	if cnt > 0 then
		return math.floor(sum / cnt)
	end
	return 0
end

-- 创建服基础信息
function createMainInfo()
	local mainInfo = {}
	mainInfo.svrIndex = Config.SVR_INDEX
	mainInfo.svrName = Config.SVR_NAME
	mainInfo.zhandouli = getMainInfoZDL()
	mainInfo.inspireCnt = nil 			-- 鼓舞次数	
	mainInfo.inspireList = nil 			-- 鼓舞列表
	mainInfo.targetSvrIndex = nil 		-- 对手服务器 0表示没有对手
	mainInfo.roadList = {}				-- 入驻列表 [roadIndex][index] = uuid
	mainInfo.fightIndexList = {} 		-- 出战索引 [roadIndex] = index
	mainInfo.fightIndexChange = nil		-- 本轮结束是否换人 [roadIndex] = boolean (true表示换人)
	mainInfo.fightWinCnt = 0 			-- 本轮胜利场数
	mainInfo.fightFailCnt = 0 			-- 本轮失败场数
	mainInfo.fightResult = nil 			-- 本轮战斗结果 [roadIndex] = 胜负
	mainInfo.fightVideo = nil 			-- 本轮战斗录像 [roadIndex] = videoUuid
	mainInfo.moveList = {} 				-- 移动列表 [uuid] = pos 
	mainInfo.logReads = {} 				-- 日志读取列表 [uuid] = boolean
	mainInfo.logs = {} 					-- 日志列表 [index] = videoUuid
	mainInfo.board = {} 				-- 排行榜 [rank] = uuid
	return mainInfo
end

-- 创建角色数据
function createPlayerData(uuid, roadIndex)
	local db = RoleDBLogic.getDb(uuid, RoleLogic.getCombatField())
	if not db then return end
	fakeHuman.db = db

	local combatType = CombatDefine.COMBAT_TYPE17
	local objList, helpList, rolebase, formation = CombatLogic.getHumanObjList(fakeHuman, combatType)
	if not objList then return end

	rolebase.tili = ValleyDefine.initTili 							-- 初始体力 每打完一场扣1
	rolebase.winCnt = 0 											-- 胜利场数
	rolebase.name = "[" .. Config.SVR_NAME .. "]" .. rolebase.name 	-- 名字拼接上服务名前缀
	rolebase.body = CombatLogic.getRoleBody(fakeHuman, combatType) 	-- 外显形象
	rolebase.time = os.time()

	local playerData = {}
	playerData._id = uuid
	playerData.roadIndex = roadIndex
	playerData.rolebase = rolebase
	playerData.objList = objList
	playerData.helpList = helpList
	playerData.formation = formation
	return playerData
end

-- 根据鼓舞次数获取额外属性
function getAttrsUp(inspireCnt1, inspireCnt2, camp)
	local cnt = 0
	if camp == CombatDefine.ATTACK_SIDE then
		cnt = inspireCnt1 - inspireCnt2
	else
		cnt = inspireCnt2 - inspireCnt1
	end
	cnt = math.min(cnt, ValleyDefine.inspireAttrCnt)
	if cnt < 1 then
		return 
	end
	local attrsUp = {}
	for _, attr in ipairs(ValleyDefine.inspireAttr) do
		local attrUp = {}
		attrUp[1] = attr[1]
		attrUp[2] = attr[2] * cnt
		attrsUp[#attrsUp + 1] = attrUp
	end
	return attrsUp
end

------------------------------------------------ msg --------------------------------------------------

-- 默认信息
local TEMP_MAIN_INFO = nil
local function getMainInfoCache()
	if not TEMP_MAIN_INFO then
		TEMP_MAIN_INFO = createMainInfo()
	end
	return TEMP_MAIN_INFO
end

-- 营地是否被攻破
function isRoadDie(data, roadIndex)
	if not data then return true end
	local fightIndex = data.fightIndexList[roadIndex] or 1
	local list = data.roadList[roadIndex]
	local listLen = list and #list or 0
	return fightIndex > listLen
end

-- 获取破营数
function getMainStar(data1, data2)
	local star = 0
	for i = 1, ROAD_MAX_CNT do
		-- （敌方阵营被攻破）敌方某路没人，己方还有人
		if isRoadDie(data2, i) and not isRoadDie(data1, i) then
			star = star + 1
		end
	end	
	return star
end

-- 封装主界面基础信息
local function fontMainInfo(net, data1, data2)
	net.svrName = data1 and data1.svrName or ""
	net.star = getMainStar(data1, data2)
	net.roadStates[0] = ROAD_MAX_CNT
	for i = 1, ROAD_MAX_CNT do
		net.roadStates[i] = 0
		-- （己方阵营被攻破）己方某路没人，敌方还有人
		if isRoadDie(data1, i) and not isRoadDie(data2, i) then
			net.roadStates[i] = 1
		end
	end
end

-- 主界面查询
local TEMP_QUERY_DATA = {}
function query(human)
	local state, leftTime = isOpen(human)
	if not state then return end

	if state ~= STATE_ACT_FIGHT then
		return sendQuery(human.db._id, TEMP_QUERY_DATA)
	end

	local msgInner = InnerMsg.lw.LW_VALLEY_QUERY
	msgInner.uuid = uuid
	InnerMsg.sendMsg(0, msgInner)
end

-- 发送主界面信息
function sendQuery(uuid, data)
	local human = ObjHuman.onlineUuid[uuid]
	if not human then return end

	local state, leftTime = data.state, data.leftTime
	if not state or not leftTime then
		state, leftTime = getState()
	end
	if not state then return end

	local msgRet = Msg.gc.GC_VALLEY_QUERY
	local dataNet = msgRet.data 
	dataNet.state = state
	dataNet.leftTime = leftTime
	dataNet.taskRed = ValleyTask.isRed(human) and 1 or 0
	dataNet.logRed = data.logRed and 1 or 0 
	local mainInfo1 = data.mainInfo1 or getMainInfoCache()
	fontMainInfo(dataNet.info1, mainInfo1, data.mainInfo2)
	fontMainInfo(dataNet.info2, data.mainInfo2, mainInfo1)

	-- 是否报名
	local signData = getSignData(uuid)
	dataNet.isSign = signData and 1 or 0
	dataNet.roadIndex = signData and signData.roadIndex or 0

	-- 探索阶段额外信息
	dataNet.exploreData[0] = 0
	if state == STATE_ACT_EXPLORE then
		dataNet.exploreData[0] = 1
		local exploreDataNet = dataNet.exploreData[1]
		exploreDataNet.time = ValleyDefine.exploreTime - leftTime
		exploreDataNet.maxTime = ValleyDefine.exploreTime
		exploreDataNet.exploreRed = isRedExplore(human) and 1 or 0
	end

	-- 战斗阶段额外信息
	dataNet.fightData[0] = 0
	if state == STATE_ACT_FIGHT then
		dataNet.fightData[0] = 1
		local fightDataNet = dataNet.fightData[1]
		fightDataNet.fightState = data.roundState or 0
		fightDataNet.leftTime = (data.roundStateEndTime - os.time()) or 0
		fightDataNet.players[0] = data.players and #data.players or 0
		for i = 1, fightDataNet.players[0] do
			Util.copyTableSimple(data.players[i], fightDataNet.players[i])
		end
	end
--	Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)
end

-- 报名
function sign(human)
	local state = isOpen(human)
	if not state then return end
	-- 是否报名阶段
	if state ~= STATE_ACT_SIGN then
		return Broadcast.sendErr(human, Lang.VALLEY_SIGN_ERR_TIME)
	end	

	-- 判断是否已报名
	if getSignData(human.db._id) then
		return Broadcast.sendErr(human, Lang.VALLEY_SIGN_ERR_HAD)
	end

	-- 未报名生成报名信息
	addSignData(human)

	-- 初始队伍取征战的阵容
	CombatPosLogic.copyCombatHeros(human, CombatDefine.COMBAT_TYPE1, CombatDefine.COMBAT_TYPE17)

	Broadcast.sendErr(human, Lang.VALLEY_SIGN_OK)
	Msg.send(Msg.gc.GC_VALLEY_SIGN, human.fd)
end

-- 封装各路入驻角色信息
function fontRoadPlayer(net, uuid)
	local db = RoleDBLogic.getDb(uuid, RoleLogic.getCombatField())
	if not db then return end

	fakeHuman.db = db
	net.uuid = uuid
	net.name = "[" .. Config.SVR_NAME .. "]" .. db.name
	net.tili = ValleyDefine.initTili	
	net.heroList[0] = 0
	-- 报名了才显示默认队伍
	local heroIndexs = CombatPosLogic.getCombatHeros(fakeHuman, CombatDefine.COMBAT_TYPE17) 
	if heroIndexs and getSignData(uuid)  then
		for pos = 1, CombatDefine.COMBAT_HERO_CNT do
			local uuid = heroIndexs[pos]
			local heroGrid = HeroLogic.getHeroGridByUuid(human, uuid)
			if heroGrid and type(heroGrid) == "table" then
				net.heroList[0] = net.heroList[0] + 1
				HeroGrid.makeHeroSimple(net.heroList[net.heroList[0]], heroGrid, pos)
			end
		end
	end
	net.zhandouli = CombatPosLogic.getCombatHeroZDL(fakeHuman, CombatDefine.COMBAT_TYPE17)
	return true
end

-- 某路的入驻信息
function queryRoad(human, camp, roadIndex)
	local state = isOpen(human)
	if not state then return end
	if roadIndex < 1 or roadIndex > ROAD_MAX_CNT then
		return
	end
	if camp ~= 1 and camp ~= 2 then return end
	if state == STATE_ACT_READY then -- 休战阶段是看不了的
		return Broadcast.sendErr(human, Lang.VALLEY_ERR_READY)
	end
	-- 只有战斗阶段可以查看敌方营地信息
	if state ~= STATE_ACT_FIGHT and camp ~= CombatDefine.ATTACK_SIDE then
		returnBroadcast.sendErr(human, Lang.VALLEY_ROAD_ERR_CAMP)
	end 
	if state == STATE_ACT_SIGN then -- 报名阶段显示本服数据即可
		return sendRoadQuery(human.db._id, camp, roadIndex)
	end

	local msgInner = InnerMsg.lw.LW_VALLEY_ROAD_QUERY
	msgInner.uuid = human.db._id 
	msgInner.camp = camp 
	msgInner.roadIndex = roadIndex
	InnerMsg.sendMsg(0, msgInner)
end

-- 发送入驻信息
function sendRoadQuery(uuid, camp, roadIndex, playerList, myData)
	local human = ObjHuman.onlineUuid[uuid]
	if not human then return end

	local msgRet = Msg.gc.GC_VALLEY_ROAD_QUERY
	msgRet.state = getState()
	msgRet.camp = camp
	msgRet.roadIndex = roadIndex
	msgRet.myRoadIndex = getRoadIndex(uuid) or 0		
	msgRet.list[0] = 0	
	if playerList then
		msgRet.cnt = playerList.cnt or 0
		msgRet.list[0] = #playerList
		for i = 1, msgRet.list[0] do
			Util.copyTableSimple(playerList[i], msgRet.list[i])
		end
	else
		local uuids = getRoadUuids(roadIndex)
		local uuidsLen = uuids and #uuids or 0
		msgRet.cnt = uuidsLen 
		for i = 1, uuidsLen do
			if msgRet.list[0] >= #msgRet.list then
				break
			end
			local uuid = uuids[i]
			if fontRoadPlayer(msgRet.list[msgRet.list[0] + 1], uuid) then
				msgRet.list[0] = msgRet.list[0] + 1
			end
		end		
	end
	if myData and myData.uuid then
		Util.copyTableSimple(myData, msgRet.myData)
	else
		fontRoadPlayer(msgRet.myData, uuid)
	end
	msgRet.isSign = getSignData(uuid) and 1 or 0
--	Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)
end

-- 发送入驻/退出路线
local function sendRoadChange(human, roadIndex)
	local msgRet = Msg.gc.GC_VALLEY_ROAD_CHANGE
	msgRet.roadIndex = roadIndex
	Msg.send(msgRet, human.fd)
end

-- 修改入驻路线
function changeRoad(human, roadIndex)
	local state = isOpen(human)
	if not state then return end
	if state ~= STATE_ACT_SIGN then
		return Broadcast.sendErr(human, Lang.VALLEY_CHANGE_ROAD_ERR_TIME)
	end	
	if roadIndex < 1 or roadIndex > ROAD_MAX_CNT then
		return
	end
	if not getSignData(human.db._id) then --先报名
		return Broadcast.sendErr(human, Lang.VALLEY_ERR_SIGN)
	end

	if roadIndex == 0 then
		-- 退出入驻
		local oldRoadIndex = delFromRoad(human.db._id)
		if oldRoadIndex and oldRoadIndex > 0 then
			sendRoadChange(human, roadIndex)
		end
	else
		-- 入驻某路
		if addToRoad(human.db._id, roadIndex) then
			sendRoadQuery(human, roadIndex)
			sendRoadChange(human, roadIndex)
		end
	end
end

-- 自动入驻路线 优先选人最少的
-- 报名了，但还没入驻
function autoChangeRoad(uuid)
	if getRoadIndex(uuid) ~= 0 then
		return 
	end

	local commonDB = getCommonDB()
	local minCnt = nil
	local minCntRoadInex = nil
	for i = 1, ROAD_MAX_CNT do
		local roadList = commonDB.roadList[i]
		local cnt = roadList and #roadList or 0
		if minCnt == nil or cnt < minCnt then
			minCnt = cnt 
			minCntRoadInex = i 
		end
	end
	if not minCntRoadInex then return end

	addToRoad(uuid, minCntRoadInex, true)
end

-- 刷新侦查列表
function refreshExplore(signData, exploreCnt)
	local isChange = nil
	for i = signData.exploreCnt + 1, exploreCnt do
		signData.exploreCnt = i
		local id, config = randomExploreID()
		if id and config then
			signData.exploreLogs[#signData.exploreLogs + 1] = id 
			signData.exploreItems = signData.exploreItems or {}
			local oldItemCnt = signData.exploreItems[config.itemID] or 0
			signData.exploreItems[config.itemID] = oldItemCnt + config.itemCnt
		end
		isChange = true
	end 
	if isChange then
		saveCommonDB(getCommonDB())
	end
end

-- 是否有侦查红点（有奖励可领取）
function isRedExplore(human)
	local state, _, startTime = isOpen(human)
	if not state then return end
	if state ~= STATE_ACT_EXPLORE then return end
	local signData = getSignData(human.db._id)
	if not signData then return end
	local exploreCnt = math.floor((os.time() - startTime) / ValleyDefine.exploreItemTime)
	refreshExplore(signData, exploreCnt)
	if signData.exploreItems then
		return true
	end
end

-- 侦查界面查询
function sendExploreQuery(human)
	local state, _, startTime = isOpen(human)
	if not state then return end
	if state ~= STATE_ACT_EXPLORE then
		return Broadcast.sendErr(human, Lang.VALLEY_EXPLORE_ERR_TIME)
	end
	local signData = getSignData(human.db._id)
	if not signData then
		return Broadcast.sendErr(human, Lang.VALLEY_ERR_SIGN)
	end
	local exploreCnt = math.floor((os.time() - startTime) / ValleyDefine.exploreItemTime)
	refreshExplore(signData, exploreCnt)

	local msgRet = Msg.gc.GC_VALLEY_EXPLORE_QUERY
	msgRet.time = os.time()
	msgRet.logs[0] = #signData.exploreLogs
	for i = 1, msgRet.logs[0] do
		local net = msgRet.logs[i]
		local id = signData.exploreLogs[i]
		local config = ValleyExcel.explore[id]
		net.time = startTime + ValleyDefine.exploreItemTime * i
		net.content = Util.format(config.content, ItemDefine.getValue(config.itemID, "name"), config.itemCnt)
	end
	msgRet.items[0] = 0
	if signData.exploreItems then
		for itemID, itemCnt in pairs(signData.exploreItems) do
			msgRet.items[0] = msgRet.items[0] + 1
			Grid.makeItem(msgRet.items[msgRet.items[0]], itemID, itemCnt)
		end
	end
	Msg.send(msgRet, human.fd)
end

-- 领取侦查奖励
function getExplore(human)
	local state = isOpen(human)
	if not state then return end
	if state ~= STATE_ACT_EXPLORE then
		return Broadcast.sendErr(human, Lang.VALLEY_EXPLORE_ERR_TIME)
	end
	local signData = getSignData(human.db._id)
	if not signData then
		return Broadcast.sendErr(human, Lang.VALLEY_ERR_SIGN)
	end
	local exploreCnt = math.floor((os.time() - startTime) / ValleyDefine.exploreItemTime)
	refreshExplore(signData, exploreCnt)

	local exploreItems = signData.exploreItems
	if not exploreItems then
		return Broadcast.sendErr(human, Lang.VALLEY_EXPLORE_GET_ERR_ITEMS)
	end 
	
	signData.exploreItems = nil 
	saveCommonDB(getCommonDB())
	for itemID, itemCnt in pairs(exploreItems) do
		BagLogic.addItem(human, itemID, itemCnt, "valley")
	end
	BagLogic.sendItemGetList(human, exploreItems, "valley")
	sendExploreQuery(human)
end

-- 封装鼓舞基本信息
local function fontInspireBase(net, mainInfo)
	net.svrName = mainInfo and mainInfo.svrName or ""
	net.cnt = mainInfo and mainInfo.inspireCnt or 0
	net.maxCnt = MAX_INSPIRE_CNT
end

local function fontInspireData(dataNet, data)
	dataNet.round = data.round
	fontInspireBase(dataNet.base1, data.mainInfo1)
	fontInspireBase(dataNet.base2, data.mainInfo2)
	dataNet.inspireItems[0] = 2
	Grid.makeItem(dataNet.inspireItems[1], ValleyDefine.inspireItem1[1], ValleyDefine.inspireItem1[2])
	Grid.makeItem(dataNet.inspireItems[2], ValleyDefine.inspireItem2[1], ValleyDefine.inspireItem2[2])
	dataNet.selectIndex = data.selectIndex or 0
end

-- 鼓舞查询 
function queryInspire(human)
	local state = isOpen(human)
	if not state then return end
	if state ~= STATE_ACT_FIGHT then
		return Broadcast.sendErr(human, Lang.VALLEY_INSPIRE_ERR_TIME)
	end

	local msgInner = InnerMsg.lw.LW_VALLEY_INSPIRE_QUERY
	msgInner.uuid = human.db._id
	InnerMsg.sendMsg(0, msgInner)
end

-- 鼓舞 
function selectInspire(human, selectIndex)
	local state = isOpen(human)
	if not state then return end
	if state ~= STATE_ACT_FIGHT then
		return Broadcast.sendErr(human, Lang.VALLEY_INSPIRE_ERR_TIME)
	end
	-- 判断花费
	local useItem = ValleyDefine["inspireItem" .. selectIndex]
	if not useItem then return end -- 选择鼓舞不存在

	local itemID = useItem[1]
	local itemCnt = useItem[2]
	if not BagLogic.checkItemCnt(human, itemID, itemCnt) then
		return
	end
	-- 通知跨服
	local msgInner = InnerMsg.lw.LW_VALLEY_INSPIRE
	msgInner.uuid = human.db._id
	InnerMsg.sendMsg(0, msgInner)	
end

-- 观战面板查询
function queryFight(human, roadIndex)
	local state = isOpen(human)
	if not state then return end
	if state ~= STATE_ACT_FIGHT then
		return Broadcast.sendErr(human, Lang.VALLEY_FIGHT_ERR_TIME)
	end
	if roadIndex < 1 or roadIndex > ROAD_MAX_CNT then
		return
	end

	local msgInner = InnerMsg.lw.LW_VALLEY_FIGHT_QUERY
	msgInner.uuid = human.db._id 
	msgInner.roadIndex = roadIndex
	InnerMsg.sendMsg(0, msgInner)
end

-- 观战
function playFight(human, videoUuid)
	local state = isOpen(human)
	if not state then return end
	if state ~= STATE_ACT_FIGHT then
		return Broadcast.sendErr(human, Lang.VALLEY_FIGHT_ERR_TIME)
	end
	if videoUuid == "" then
		return Broadcast.sendErr(human, Lang.VALLEY_FIGHT_ERR_DOING)
	end

	local msgInner = InnerMsg.lw.LW_VALLEY_PLAY_FIGHT
	msgInner.uuid = human.db._id 
	msgInner.videoUuid = videoUuid
	InnerMsg.sendMsg(0, msgInner)	
end

-- 日志查看
function queryLog(human, roadIndex)
	local state = isOpen(human)
	if not state then return end
	if roadIndex < 0 or roadIndex > ROAD_MAX_CNT then
		return
	end

	local msgInner = InnerMsg.lw.LW_VALLEY_LOG_QUERY
	msgInner.uuid = human.db._id 
	msgInner.roadIndex = roadIndex
	InnerMsg.sendMsg(0, msgInner)		
end

-- 排行榜查看
function queryBoard(human, camp)
	local state = isOpen(human)
	if not state then return end
	if camp ~= 1 and camp ~= 2 then
		return
	end

	local msgInner = InnerMsg.lw.LW_VALLEY_BOARD_QUERY
	msgInner.uuid = human.db._id 
	msgInner.camp = camp
	InnerMsg.sendMsg(0, msgInner)		
end

-- 可否打开上阵面板
function checkCombatPos(human)
	local state = isOpen(human)
	if not state then return end -- 未达到开放条件

	if state == STATE_ACT_FIGHT then -- 开打了，不可以
		return Broadcast.sendErr(human, Lang.VALLEY_COMBAT_POS_ERR_TIME)
	end

	if state ~= STATE_ACT_SIGN then
		local roadIndex = getRoadIndex(uuid)
		if not roadIndex then -- 错过报名阶段，还没报名，不让改阵容
			return Broadcast.sendErr(human, Lang.VALLEY_COMBAT_POS_ERR_SIGN)
		end
		if roadIndex == 0 then -- 错过报名阶段，没入驻，不让改阵容
			return Broadcast.sendErr(human, Lang.VALLEY_COMBAT_POS_ERR_ROAD)
		end
	end
	return true 
end

-- 刷新上阵信息
function onUpdate(human)
	local uuid = human.db._id
	local roadIndex = getRoadIndex(uuid)
	if not roadIndex then return end

	local state = getState()
	if state == STATE_ACT_FIGHT then
		return
	end

	sendLWRoadPlayer(uuid, roadIndex)
end

-------------------------------------- middle -------------------------------------------
-- 主界面
function WL_VALLEY_QUERY(uuid, data)
	sendQuery(uuid, data)
end

-- 营地查询
function WL_VALLEY_ROAD_QUERY(uuid, camp, roadIndex, playerList, myData)
	sendRoadQuery(uuid, camp, roadIndex, playerList, myData)
end

-- 鼓舞界面返回
function WL_VALLEY_INSPIRE_QUERY(uuid, data)
	local human = ObjHuman.onlineUuid[uuid]
	if not human then return end

	local msgRet = Msg.gc.GC_VALLEY_INSPIRE_QUERY
	msgRet.leftTime = data.leftTime
	fontInspireData(msgRet.data, data)
	Msg.send(msgRet, human.fd)
end

-- 鼓舞
function WL_VALLEY_INSPIRE(uuid, selectIndex)
	local human = ObjHuman.onlineUuid[uuid]
	if not human then return end

	-- 判断花费
	local useItem = ValleyDefine["inspireItem" .. selectIndex]
	if not useItem then return end -- 选择鼓舞不存在

	local itemID = useItem[1]
	local itemCnt = useItem[2]
	if not BagLogic.checkItemCnt(human, itemID, itemCnt) then
		return
	end
	BagLogic.delItem(human, itemID, itemCnt, "valley_inspire")	
end

-- 观战界面
function WL_VALLEY_FIGHT_QUERY(uuid, data)
	local human = ObjHuman.onlineUuid[uuid]
	if not human then return end

	local msgRet = Msg.gc.GC_VALLEY_FIGHT_QUERY
	msgRet.fightState = data.fightState or 0
	fontInspireData(msgRet.inspireData, data)
	msgRet.fightPlayers[0] = data.fightPlayers and #data.fightPlayers or 0
	for i = 1, msgRet.fightPlayers[0] do
		Util.copyTableSimple(data.fightPlayers[i], msgRet.fightPlayers[i])
	end
	msgRet.fightBase[0] = data.fightBase and #data.fightBase or 0
	for i = 1, msgRet.fightBase[0] do
		Util.copyTableSimple(data.fightBase[i], msgRet.fightBase[i])
	end
	msgRet.videoUuid = data.videoUuid or ""
	Msg.send(msgRet, human.fd)	
end

-- 观战
function WL_VALLEY_PLAY_FIGHT(uuid, combatInfo)
	local human = ObjHuman.onlineUuid[uuid]
	if not human then return end

	CombatLogic.repeatCombat(human, combatInfo)
end

-- 开打
function WL_VALLEY_COMBAT_BEGIN(svrIndex, roadIndex, round, inspireCnt1, inspireCnt2, playerData1, playerData2)
	-- 开打
	local cbParam = {}
	cbParam.svrIndex = svrIndex
	cbParam.roadIndex = roadIndex 
	cbParam.inspireCnt1 = inspireCnt1
	cbParam.inspireCnt2 = inspireCnt2
	cbParam.round = round
	cbParam.hpRateListAtk = playerData1.hpRateList
	cbParam.hpRateListDef = playerData2.hpRateList

	local param = {}
	param.attacker = playerData1.objList
	param.atkHelp = playerData1.helpList
	param.atkRBase = playerData1.rolebase
	param.atkFormation = playerData1.formation
	param.defender = playerData2.objList
	param.defHelp = playerData2.helpList
	param.defRBase = playerData2.rolebase
	param.defFormation = playerData2.formation
	fakeHuman.db = nil
	CombatLogic.combatBegin(fakeHuman, 1001, param, CombatDefine.COMBAT_TYPE17, cbParam, true)	
end

-- 战斗前加属性
function onFightBegin(human, cbParam)
	local attrsUp1 = getAttrsUp(cbParam.inspireCnt1, cbParam.inspireCnt2, CombatDefine.ATTACK_SIDE)
	local attrsUp2 = getAttrsUp(cbParam.inspireCnt1, cbParam.inspireCnt2, CombatDefine.DEFEND_SIDE)

	for index = 1, CombatDefine.COMBAT_HERO_CNT do	
		-- 攻击	
		local atkPos = CombatLogic.getPos(CombatDefine.ATTACK_SIDE, index)
		local atkObj = CombatImpl.objList[atkPos]
		if atkObj then			
			atkObj.isSysAttrChange = true	
			if attrsUp1 then	    
				local initAttr = atkObj.initAttr --基础属性
				for _, attrUp in ipairs(attrsUp1) do
					initAttr[attrUp[1]] = initAttr[attrUp[1]] + attrUp[2]
				end
			end
        end		
        -- 防守
		local defPos = CombatLogic.getPos(CombatDefine.DEFEND_SIDE, index)
		local defObj = CombatImpl.objList[defPos]
		if defObj then
			defObj.isSysAttrChange = true
			if attrsUp2 then
	            local initAttr = defObj.initAttr --基础属性
				for _, attrUp in ipairs(attrsUp2) do
					initAttr[attrUp[1]] = initAttr[attrUp[1]] + attrUp[2]
				end
			end
		end
	end
end

-- 战斗结束回调
function onFightEnd(human, result, combatType, cbParam, combatInfo, isSaodang)
	print("fight end", result, combatInfo, result)

	-- 如果两边都没死，按照
	calcCombatResult(combatInfo)

	combatInfo.inspireCnt1 = cbParam.inspireCnt1
	combatInfo.inspireCnt2 = cbParam.inspireCnt2
	combatInfo.roadIndex = roadIndex
	combatInfo.round = round

	local msgInner = InnerMsg.lw.LW_VALLEY_COMBATINFO
	msgInner.svrIndex = cbParam.svrIndex
	msgInner.combatInfo = combatInfo
	InnerMsg.sendMsg(0, msgInner)
end

-- 刷新记录的血量+双方未死时，重新定义胜负(血量多胜出)
function calcCombatResult(combatInfo)
	local hpRateListAtk = {}
	local hpRateListDef = {}
	local hpSumAtk = 0
	local hpSumDef = 0
	for index = 1, CombatDefine.COMBAT_HERO_CNT do
        -- 更新攻击方血量
        local atkPos = CombatLogic.getPos(CombatDefine.ATTACK_SIDE, index)
        local atkObj = combatInfo.objList[atkPos]
        if atkObj ~= nil then
			local hp = atkObj.hp
			local hpMax = CombatObj.getHpMax(atkObj)
			local hpRate = hp / hpMax
			hpRateListAtk[index] = hpRate
			hpSumAtk = math.max(hp, 0) + hpSumAtk
        end		
        -- 更新防守方血量
        local defPos = CombatLogic.getPos(CombatDefine.DEFEND_SIDE, index)
        local defObj = combatInfo.objList[defPos]
        if defObj ~= nil then
        	local hp = defObj.hp
			local hpMax = CombatObj.getHpMax(defObj)
			local hpRate = hp / hpMax
		   	hpRateListDef[index] = hpRate
		   	hpSumDef = math.max(hp, 0) + hpSumDef
        end
	end  
	combatInfo.isWin = hpSumAtk >= hpSumDef
	combatInfo.hpRateListAtk = hpRateListAtk
	combatInfo.hpRateListDef = hpRateListDef
end

-- 所有属性计算完毕，重新设置血量(攻击)
function calcAttr(side, index, obj, cbParam)
	local hpRateList = nil
	if side == CombatDefine.ATTACK_SIDE then
		hpRateList = cbParam.hpRateListAtk
	else
		hpRateList = cbParam.hpRateListDef
	end
	if not hpRateList then return end
	local hpRate = hpRateList[index]
	if not hpRate then return end

	local hpMax = CombatObj.getHpMax(obj)
	obj.hp = math.ceil(hpRate * hpMax)
end

-- 战斗刷新 如果客户端处于观战面板且对应营地 重新请求CG_VALLEY_FIGHT_QUERY
function WL_VALLEY_FIGHT_QUERY_REFRESH(roadIndex)
	local msgRet = Msg.gc.GC_VALLEY_FIGHT_QUERY_REFRESH
	msgRet.roadIndex = roadIndex
	Msg.sendWorld(msgRet)
end

-- 日志
function WL_VALLEY_LOG_QUERY(uuid, roadIndex, logs)
	local human = ObjHuman.onlineUuid[uuid]
	if not human then return end

	local msgRet = Msg.gc.GC_VALLEY_LOG_QUERY
	msgRet.roadIndex = roadIndex
	msgRet.logs[0] = #logs
	for i = 1, msgRet.logs[0] do
		Util.copyTableSimple(logs[i], msgRet.logs[i])
	end
--	Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)
end

-- 排行榜
function WL_VALLEY_BOARD_QUERY(uuid, camp, list, myData)
	local human = ObjHuman.onlineUuid[uuid]
	if not human then return end

	local msgRet = Msg.gc.GC_VALLEY_BOARD_QUERY
	msgRet.camp = camp 
	Util.copyTableSimple(myData, msgRet.myData)
	if myData.roleBase == nil then
		msgRet.myData.killCnt = 0
		RoleLogic.makeRoleBase(human.db, msgRet.myData.roleBase)
	end
	msgRet.list[0] = #list
	for i = 1, msgRet.list[0] do
		Util.copyTableSimple(list[i], msgRet.list[i])
	end
--	Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)
end

-- 计算破营奖励
function calcRoadItems(roadItems, items, cnt)
	if cnt < 1 then return end
	for _, item in pairs(items) do
		local itemID = item[1]
		local itemCnt = item[2] * cnt

		local selectIndex = #roadItems + 1
		for index, item2 in ipairs(roadItems) do
			if item2[1] == itemID then
				selectIndex = index
				break
			end
		end
		roadItems[selectIndex] = roadItems[selectIndex] or {}
		roadItems[selectIndex][1] = itemID
		roadItems[selectIndex][2] = (roadItems[selectIndex][2] or 0) + itemCnt	
	end
	return roadItems
end

-- 破营+杀敌奖励+刷新成就
function WL_VALLEY_FINAL_RESULT(killList, winCnt, failCnt, tieCnt)
	local roadMailConfig = MailExcel.mail[114]
	local roadContent = Util.format(roadMailConfig.content, winCnt, failCnt, tieCnt)
	local killMailConfig = MailExcel.mail[115]
	local roadItems = {}
	calcRoadItems(roadItems, ValleyDefine.roadWinItem, winCnt)
	calcRoadItems(roadItems, ValleyDefine.roadFailItem, failCnt)
	calcRoadItems(roadItems, ValleyDefine.roadTieItem, tieCnt)
	for uuid, killCnt in pairs(killList) do
		-- 杀敌奖励
		local killConfig = ValleyExcel.kill[killCnt]
		if killConfig then
			local content = Util.format(killMailConfig.content, killCnt)
			MailManager.add(MailManager.SYSTEM, uuid, killMailConfig.title, content, killConfig.reward, killMailConfig.senderName)
		end
		-- 破营奖励
		MailManager.add(MailManager.SYSTEM, uuid, roadMailConfig.title, roadContent, roadItems, roadMailConfig.senderName)
		-- 成就刷新
		ValleyTask.updateValue(uuid, killCnt, winCnt)
	end
end

-- 每轮鼓舞奖励
function WL_VALLEY_INSPIRE_RESULT(inspireList, winCnt, failCnt)
	local config = ValleyExcel.inspire[winCnt]
	if not config then return end

	local msgRet = Msg.gc.GC_VALLEY_INSPIRE_RESULT
	msgRet.winCnt = winCnt
	msgRet.failCnt = failCnt
	for uuid, selectIndex in pairs(inspireList) do
		local human = ObjHuman.onlineUuid[uuid]
		local inspireItem = ValleyDefine["inspireItem" .. selectIndex]
		if human and inspireItem then
			BagLogic.addItem(human, inspireItem[1], inspireItem[2], "valley_inspire")

			msgRet.items[0] = 1
			Grid.makeItem(msgRet.items[1], inspireItem[1], inspireItem[2])
			Msg.send(msgRet, human.fd)
		end
	end
end

------------------------------------- 活动状态变化 ------------------------------------------
-- 发送角色数据
function sendLWRoadPlayer(uuid, roadIndex)
	local playerData = createPlayerData(uuid, roadIndex)
	if not playerData then return end

	local msgInner = InnerMsg.lw.LW_VALLEY_ROAD_PLAYER
	msgInner.playerData = playerData
	InnerMsg.sendMsg(0, msgInner)
end

-- 数据上传跨服+匹配对手 
function onActMatch()
	if _G.is_middle then return end

	local commonDB = getCommonDB()
	-- 未入驻的自动入驻
	if commonDB.signList then
		for uuid, roadIndex in pairs(commonDB.signList) do
			if roadIndex == 0 then
				autoChangeRoad(uuid)
			end
		end
	end
	
	commonDB.roadListSend = {}
	if commonDB.roadList then
		for roadIndex, list in pairs(commonDB.roadList) do
			for _, uuid in ipairs(list) do
				local data = {}
				data.uuid = uuid
				data.roadIndex = roadIndex
				commonDB.roadListSend[#commonDB.roadListSend + 1] = data
			end
		end
	end
	saveCommonDB(commonDB)

	local msgInner = InnerMsg.lw.LW_VALLEY_MAIN_INFO
	msgInner.data = createMainInfo()
	InnerMsg.sendMsg(0, msgInner)
end

-- 匹配阶段定时器
function onTimerActMatch(commonDB)
	if not commonDB.roadListSend then return end

	local cnt = 0
	local len = #commonDB.roadListSend
	for i = len, 1, -1 do
		if cnt >= TIMER_SEND_DATA then
			break
		end

		local data = commonDB.roadListSend[i]
		commonDB.roadListSend[i] = nil
		sendLWRoadPlayer(data.uuid, data.roadIndex)
		cnt = cnt + 1
	end

	if #commonDB.roadListSend < 1 then
		commonDB.roadListSend = nil
	end
	saveCommonDB(commonDB)
end

-- 侦查开始/匹配结束
function onActExplore()
	if _G.is_middle then
		ValleyMiddle.onActExplore()
	end
end

-- 战斗开始
function onActFight()
	local commonDB = getCommonDB()
	commonDB.round = nil
	commonDB.roundState = nil
	commonDB.roundStateEndTime = nil
	saveCommonDB(commonDB)
end

-- 战斗阶段轮次状态切换
function onActRound(round, roundState)
	print("onActRound", round, roundState)

	if _G.is_middle then
		return ValleyMiddle.onActRound(round, roundState)
	end
end

-- 战斗阶段定时器
function onTimerActFight(commonDB)
	local round, roundState, roundStateEndTime = getNewRound(commonDB.startTime)
	commonDB.round = commonDB.round or 1
	commonDB.roundState = commonDB.roundState or 0
	if commonDB.round > round then
		return
	end
	if commonDB.round == round and commonDB.roundState >= roundState then
		return
	end

	local newRoundState = commonDB.roundState + 1
	local newRound = commonDB.round 
	if newRoundState > STATE_FIGHT_FIGHT then
		newRoundState = STATE_FIGHT_MOVE
		newRound = newRound + 1
	end
	commonDB.round = newRound
	commonDB.roundState = newRoundState
	commonDB.roundStateEndTime = roundStateEndTime
	saveCommonDB(commonDB)
	onActRound(newRound, newRoundState)
end

-- 活动结束
function onActEnd()
	if _G.is_middle then
		return ValleyMiddle.onActEnd()
	end

	cleanDB()
end

-- 活动开始
function onActStart()
	if _G.is_middle then
		return ValleyMiddle.onActStart()
	end

	cleanDB()
end


-- 定时器
local TEMP_TIMER_STAMPTIME = nil
local TEMP_TIMER_STAMPTIME2 = nil
function onTimer()	
	if not TEMP_TIMER_STAMPTIME then
		_, TEMP_TIMER_STAMPTIME, TEMP_TIMER_STAMPTIME2 = getNewState()
	end

	local nowTime = os.time()
	local commonDB = getCommonDB()
	if (not commonDB.endTime) or 
		(commonDB.endTime <= nowTime) or
		(commonDB.endTime ~= TEMP_TIMER_STAMPTIME) or 
		(commonDB.startTime ~= TEMP_TIMER_STAMPTIME2) then
		local oldState = commonDB.state
		local state, endTime, startTime = getNewState()
		commonDB.state = state
		commonDB.endTime = endTime
		commonDB.startTime = startTime
		TEMP_TIMER_STAMPTIME = endTime
		TEMP_TIMER_STAMPTIME2 = startTime
		saveCommonDB(commonDB)

		print("valley state",state, oldState, endTime)
		if state == STATE_ACT_READY then
			onActEnd()
		elseif state == STATE_ACT_MATCH then
			onActMatch()
		elseif state == STATE_ACT_FIGHT then
			onActFight()
		elseif state == STATE_ACT_EXPLORE then
			onActExplore()
		elseif state == STATE_ACT_SIGN then
			onActStart()
		end
	end

	-- 战斗阶段
	if commonDB.state == STATE_ACT_FIGHT then
		onTimerActFight(commonDB)	
	elseif commonDB.state == STATE_ACT_MATCH then
		onTimerActMatch(commonDB)	
	end
end


-- 返回活动列表的状态
function getActState()
	if MiddleConnect.IS_MIDDLE_CONNECT ~= true then
		return JjcActLogic.STATE_NOOPEN, 0
	end	

	local state, leftTime = getState()
	if state == STATE_ACT_READY then
		return JjcActLogic.STATE_READY, leftTime
	end
	return JjcActLogic.STATE_START, leftTime 
end

-- 描述
function getActDesc(desc)
	if MiddleConnect.IS_MIDDLE_CONNECT then
		return Lang.MIDDLE_SVR_ERR_CONNECT
	end		
	return desc
end
